package com.student.education.service.impl;

import com.github.pagehelper.PageHelper;
import com.student.education.common.CommonPage;
import com.student.education.dao.CountAnalysisDao;
import com.student.education.dao.ExamScoreDao;
import com.student.education.dao.UserDao;
import com.student.education.entity.ConsumptionCountOne;
import com.student.education.entity.ConsumptionCountTwo;
import com.student.education.service.CountAnalysisService;
import com.student.education.service.UserService;
import com.student.education.to.*;
import com.student.education.vo.AnalysisVo;
import com.student.education.vo.ConsumptionVo;
import com.student.education.vo.CountAnalysisNewVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author 杨豹
 * @create 2021/10/14 0014 21:20
 * @description 描述
 */

@Service
public class CountAnalysisServiceImpl implements CountAnalysisService {

    @Autowired
    CountAnalysisDao analysisDao;
    @Resource
    private UserDao userDao;
    //这个用来存储生成的项集
    private static List<String[]> resultarray = new ArrayList<String[]>();
    @Resource
    private ExamScoreDao examScoreDao;
    @Autowired
    UserService userService;

    @Override
    public CountAnalysisTo queryById(List<Integer> userId) {
        CountAnalysisTo to = new CountAnalysisTo();
        //平均值
        List<Double> avgCount = analysisDao.queryAvgCount(userId);
        to.setAvgCount(avgCount);
        //最小值
        List<Double> minCount = analysisDao.queryMinCount(userId);
        to.setMinCount(minCount);
        //最大值
        List<Double> maxCount = analysisDao.queryMaxCount(userId);
        to.setMaxCount(maxCount);
        //总计
        List<Integer> countAll = analysisDao.queryAllCount(userId);
        to.setCountAll(countAll);
        //正常最小值
        int[] normalMinNum = {16, 3, 5, 3, 15};
        List<Integer> normalMin = Arrays.stream(normalMinNum).boxed().collect(Collectors.toList());
        to.setNormalMin(normalMin);
        //正常最大值
        int[] normalMaxNum = {30, 10, 10, 6, 20};
        List<Integer> normalMax = Arrays.stream(normalMaxNum).boxed().collect(Collectors.toList());
        to.setNormalMax(normalMax);

        List<List<Integer>> lineData1 = new ArrayList<>();
        List<Integer> lineData1One = analysisDao.lineData1One(userId);
        lineData1.add(lineData1One);
        List<Integer> lineData1Two = analysisDao.lineData1Two(userId);
        lineData1.add(lineData1Two);
        List<Integer> lineData1Three = analysisDao.lineData1Three(userId);
        lineData1.add(lineData1Three);
        List<Integer> lineData1Four = analysisDao.lineData1Four(userId);
        lineData1.add(lineData1Four);
        List<Integer> lineData1Five = analysisDao.lineData1Five(userId);
        lineData1.add(lineData1Five);
        to.setLineData1(lineData1);

        List<List<Double>> lineData2 = new ArrayList<>();
        List<Double> lineData1OneOne = analysisDao.lineData1OneOne(userId);
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
        to.setLineData2(lineData2);

        to.setOneNum(lineData1One);
        to.setTwoNum(lineData1Two);
        to.setThreeNum(lineData1Three);
        to.setFourNum(lineData1Four);
        to.setFiveNum(lineData1Five);
        to.setSixNum(lineData1OneOne);
        return to;
    }

    @Override
    public AnalysisTo situationAnalysis(AnalysisVo vo) {
        List<String> analysis = analysisDao.situationAnalysis(vo);

        for (int i = 0; i < analysis.size(); i++) {
            if (Objects.equals(analysis.get(i), "")) {
                continue;
            }
            String[] arr = analysis.get(i).split(",");
            runSelect(arr);
        }

        //调用分析程序
        Map<String, Integer> map = analysis(resultarray);

        //输出统计结果
        return printMap(map, 5);
    }

    @Override
    public List<MyClassStudentTo> selectMyStudents(Integer userId) {
        UserTo userTo = userDao.queryById(userId);
        //学生
        if (Objects.equals(userTo.getRoleId(), "3")) {
            List<MyClassStudentTo> subject = analysisDao.queryByStudentsIdSubject(userTo.getClassId());
            List<MyClassStudentTo> clazz = analysisDao.queryById(userTo.getClassId());
            List<MyClassStudentTo> myClassStudentTos = classStudentTree(subject, clazz);
            List<MyClassStudentTo> students = analysisDao.queryByIdStudents(userId);
            return classStudentTree(myClassStudentTos, students);
        } else if (Objects.equals(userTo.getRoleId(), "4")) {//辅导员
            List<MyClassStudentTo> subject = analysisDao.queryByStudentsIdSubject(userTo.getClassId());
            List<MyClassStudentTo> clazz = analysisDao.queryById(userTo.getClassId());
            List<MyClassStudentTo> myClassStudentTos = classStudentTree(subject, clazz);
            List<MyClassStudentTo> students = analysisDao.queryByStudentsClass(userTo.getClassId());
            return classStudentTree(myClassStudentTos, students);
        } else {
            List<MyClassStudentTo> subject = analysisDao.queryAllSubject();
            List<MyClassStudentTo> clazz = analysisDao.queryAllClass();
            List<MyClassStudentTo> myClassStudentTos = classStudentTree(subject, clazz);
            List<MyClassStudentTo> students = analysisDao.queryAllStudentsClass();
            return classStudentTree(myClassStudentTos, students);
        }

    }

    @Override
    public CountAnalysisNewTo queryByIdNew(CountAnalysisNewVo vo) {
        CountAnalysisNewTo to = new CountAnalysisNewTo();
        //平均值
        List<Double> avgCount = analysisDao.queryAvgCountNew(vo);
        to.setAvgCount(avgCount);
        //最小值
        List<Double> minCount = analysisDao.queryMinCount(vo.getUserIds());
        to.setMinCount(minCount);
        //最大值
        List<Double> maxCount = analysisDao.queryMaxCount(vo.getUserIds());
        to.setMaxCount(maxCount);
        //总计
        List<Integer> countAll = analysisDao.queryAllCount(vo.getUserIds());
        to.setCountAll(countAll);
        //正常最小值
        int[] normalMinNum = {16, 3, 5, 3, 15};
        List<Integer> normalMin = Arrays.stream(normalMinNum).boxed().collect(Collectors.toList());
        to.setNormalMin(normalMin);
        //正常最大值
        int[] normalMaxNum = {30, 10, 10, 6, 20};
        List<Integer> normalMax = Arrays.stream(normalMaxNum).boxed().collect(Collectors.toList());
        to.setNormalMax(normalMax);

        List<List<Integer>> lineData1 = new ArrayList<>();
        List<Integer> lineData1One = analysisDao.lineData1One(vo.getUserIds());
        lineData1.add(lineData1One);
        List<Integer> lineData1Two = analysisDao.lineData1Two(vo.getUserIds());
        lineData1.add(lineData1Two);
        List<Integer> lineData1Three = analysisDao.lineData1Three(vo.getUserIds());
        lineData1.add(lineData1Three);
        List<Integer> lineData1Four = analysisDao.lineData1Four(vo.getUserIds());
        lineData1.add(lineData1Four);
        List<Integer> lineData1Five = analysisDao.lineData1Five(vo.getUserIds());
        lineData1.add(lineData1Five);
        to.setLineData1(lineData1);

        List<List<Double>> lineData2 = new ArrayList<>();
        List<Double> lineData1OneOne = analysisDao.lineData1OneOne(vo.getUserIds());
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
        lineData2.add(lineData1OneOne);
//        to.setLineData2(lineData2);

        to.setOneNum(lineData1One);
        to.setTwoNum(lineData1Two);
        to.setThreeNum(lineData1Three);
        to.setFourNum(lineData1Four);
        to.setFiveNum(lineData1Five);
//        to.setSixNum(lineData1OneOne);
        return to;
    }

    @Override
    public CommonPage<ExamScoreQueryTo> situationCountScore(CountAnalysisNewVo vo) {
        List<ExamScoreQueryTo> list = examScoreDao.queryMyStudentScoreNew(vo);
        return CommonPage.restPage(list);
    }

    @Override
    public ConsumptionCountTo consumptionCount(CountAnalysisNewVo vo) {
        ConsumptionCountTo list = new ConsumptionCountTo();

        List<ConsumptionCountOne> type = analysisDao.consumptionCountOne(vo);
        list.setType(type);
        List<ConsumptionCountTwo> month = analysisDao.consumptionCountTwo(vo);
        list.setMonth(month);
        list.setCount(analysisDao.consumptionCountThree(vo));

        return list;
    }

    public static List<MyClassStudentTo> classStudentTree(List<MyClassStudentTo> departs, List<MyClassStudentTo> managers) {
        for (MyClassStudentTo depart : departs) {
            if (depart.getChildren() == null) {
                List<MyClassStudentTo> list = new ArrayList<>();
                for (MyClassStudentTo manager : managers) {
                    if (Objects.equals(depart.getId(), manager.getPid())) {
                        list.add(manager);
                    }
                }
                depart.setChildren(list);
            } else {
                classStudentTree(depart.getChildren(), managers);
            }
        }
        return departs;
    }


    public static void select(List<String> selector, List<String> data, int n) {
        if (n == 0) {
            String[] result = new String[selector.size()];
            result = selector.toArray(result);
            resultarray.add(result);
            return;
        }
        if (data.isEmpty()) {
            return;
        }

        selector.add(data.get(0));
        select(selector, data.subList(1, data.size()), n - 1);
        selector.remove(selector.size() - 1);
        select(selector, data.subList(1, data.size()), n);
    }

    public static void runSelect(String[] arr) {
        for (int i = 1; i <= arr.length; i++) {
            select(new ArrayList<>(), Arrays.asList(arr), i);
        }
    }

    public static Map<String, Integer> analysis(List<String[]> resultarray) {
        HashMap<String, Integer> map = new HashMap<>();
        for (String[] goods : resultarray) {
            Arrays.sort(goods);
            map.put(Arrays.toString(goods), map.get(Arrays.toString(goods)) == null ? 1 : map.get(Arrays.toString(goods)) + 1);
        }
        Map<String, Integer> sortedmap = new LinkedHashMap();
        map.entrySet().stream()
                .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
                .forEachOrdered(x -> sortedmap.put(x.getKey(), x.getValue()));
        return sortedmap;
    }

    /**
     * @param map 需要打印的结果集
     * @param num 打印前几个
     */
    static AnalysisTo printMap(Map<String, Integer> map, int num) {

        AnalysisTo to = new AnalysisTo();
        List<String> title = new ArrayList<>();
        List<Integer> number = new ArrayList<>();

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            title.add(entry.getKey());
            number.add(entry.getValue());
            num--;
            if (num < 0) {
                return null;
            }
        }
        to.setTitle(title);
        to.setNum(number);
        return to;
    }
}
